package client;

import java.io.IOException;

import org.apache.log4j.Logger;

import common.messages.KVMessage;
import common.messages.KVMessageImpl;
import communicationLogic.ClientSocket;

public class KVStore implements KVCommInterface {
	private Logger logger = Logger.getRootLogger();
	private KVMessage ans;
	private ClientSocket clientSocket;

	/**
	 * Initialize KVStore with address and port of KVServer
	 * 
	 * @param address
	 *            the address of the KVServer
	 * @param port
	 *            the port of the KVServer
	 */
	public KVStore(String address, int port) {
		try {
			clientSocket = new ClientSocket(address, port);
			logger.info("ClientSocket established");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Establishes the connection to the KV Server.
	 * 
	 * @throws Exception
	 *             if connection could not be established.
	 */
	@Override
	public void connect() throws Exception {
		// TODO Auto-generated method stub
		clientSocket.connect();
		logger.info("Connection established");
	}

	/**
	 * disconnects the client from the currently connected server.
	 */
	@Override
	public void disconnect() {
		// TODO Auto-generated method stub
		try {
			clientSocket.disConnect();
			logger.info("Connection closed");
		} catch (Exception e) {
		}
	}

	/**
	 * Inserts a key-value pair into the KVServer.
	 * 
	 * @param key
	 *            the key that identifies the given value.
	 * @param value
	 *            the value that is indexed by the given key.
	 * @return a message that confirms the insertion of the tuple or an error.
	 * @throws Exception
	 *             if put command cannot be executed (e.g. not connected to any
	 *             KV server).
	 */
	@Override
	public synchronized KVMessage put(String key, String value) throws Exception {
		// TODO Auto-generated method stub
		KVMessageImpl kvm = new KVMessageImpl(key, value, "PUT");
		byte[] message = kvm.toByteArray(kvm);
		clientSocket.send(message);
		logger.info("Message sent" + message.toString());
		byte[] answer = clientSocket.receive();
		this.setAns(KVMessageImpl.toKVMessage(answer));
		logger.info("Answer received" + answer.toString());

		return ans;
	}

	/**
	 * Retrieves the value for a given key from the KVServer.
	 * 
	 * @param key
	 *            the key that identifies the value.
	 * @return the value, which is indexed by the given key.
	 * @throws Exception
	 *             if put command cannot be executed (e.g. not connected to any
	 *             KV server).
	 */

	@Override
	public synchronized KVMessage get(String key) throws Exception{
		// TODO Auto-generated method stub
		KVMessageImpl kvm = new KVMessageImpl(key, "", "GET");
		byte[] message = kvm.toByteArray(kvm);
		clientSocket.send(message);
		logger.info("Message sent" + message.toString());
		byte[] answer = clientSocket.receive();
		this.setAns(KVMessageImpl.toKVMessage(answer));
		logger.info("Answer received" + answer.toString());

		return ans;
	}

	public KVMessage getAns() {
		return ans;
	}

	public void setAns(KVMessage ans) {
		this.ans = ans;
	}

	public ClientSocket getClientSocket() {
		return this.clientSocket;
	}

}
